﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Security.Cryptography;
using System.Text;
using System.Threading.Tasks;
using System.Web;
using System.Xml;
using AutoMapper;
using Company.Project.Infrastructure.Common;
using Company.Project.Domain.Base;
using Company.Project.Domain.MainModule.Interface;
using Company.Project.Domain.Model;
using Company.Project.Domain.Model.DTO.Manager;
using Company.Project.Infrastructure.Common.Enums;
using Newtonsoft.Json;
using Company.Utility;
using Company.Utility.Encrypt;
using Microsoft.AspNetCore.Http;
using HttpContext=Company.Utility.HttpContext;

namespace Company.Project.Domain.MainModule
{
    public class Project_Manager_BaseInfoDomainServices : IProject_Manager_BaseInfoDomainServices
    {
        private readonly IProject_Manager_BaseInfoRepository _repository;
        private readonly IProject_SYS_ModuleDomainServices _moduleDomainServices;
        private readonly IProject_SYS_ModuleActionRepository _moduleActionRepository;
        private readonly IProject_Manager_RoleRepository _roleRepository;
        public Project_Manager_BaseInfoDomainServices(IProject_Manager_BaseInfoRepository repository, IProject_SYS_ModuleDomainServices moduleDomainServices,
            IProject_SYS_ModuleActionRepository moduleActionRepository, IProject_Manager_RoleRepository roleRepository)
        {
            this._repository = repository;
            _moduleDomainServices = moduleDomainServices;
            _moduleActionRepository = moduleActionRepository;
            _roleRepository = roleRepository;
        }
        /// <summary>
        /// 检测登录
        /// </summary>
        /// <param name="loginName"></param>
        /// <param name="passWord"></param>
        /// <param name="remmberMe"></param>
        /// <param name="pwdIsMd5"></param>
        /// <param name="validateCode"></param>
        /// <param name="configureAwait"></param>
        /// <param name="context"></param>
        /// <returns></returns>
        public async Task<LoginUserDTO> CheckLogin(string loginName, string passWord, bool remmberMe, bool? pwdIsMd5 = false, string validateCode = null)
        {
            var data = new LoginUserDTO();
            if (loginName == "" || passWord == "")
            {
                throw new CustomException("请输入账号密码!");
            }
            if (pwdIsMd5 == false)
            {
                if (!string.IsNullOrEmpty(validateCode))
                {
                    HttpContext.Current.Request.Cookies.TryGetValue("ValidateKey", out string key);
                    if (string.IsNullOrEmpty(key))
                    {
                        throw new CustomException("验证码失效,请重试!");
                    }
                    var validateCacheCode = new DataCache().GetCache<dynamic>(key);
                    if (string.IsNullOrEmpty(validateCacheCode))
                    {
                        throw new CustomException("验证码失效,请重试!");
                    }
                    if (validateCode != validateCacheCode)
                    {
                        throw new CustomException("验证码错误,请重试!");
                    }
                }
                else
                {
                    throw new CustomException("请输入验证码!");
                }
            }
            var user = await 
                _repository.GetLoginUser(
                    new DirectSpecification<Project_Manager_BaseInfo>(
                        x => !x.IsDeleted && x.LoginName == loginName));
            if (null == user)
            {
                throw new CustomException("账号或密码错误,请重试!");
            }
            else
            {
                if (user.PassWord!=
                    Convert.ToBase64String(new SHA256Managed().ComputeHash(Encoding.UTF8.GetBytes(passWord+ user.ID))))
                {
                    throw new CustomException("账号或密码错误,请重试!");
                }
                if (user.State == Enum_ManagerUserState.Locked)
                {
                    throw new CustomException("该用户已被锁定!");
                }
                else
                {
                    data = await BindDTO(user);
                    //记录登录时间和IP
                    if (validateCode != null)
                    {
                        user.LastLoginIP = user.ThisLoginIP;
                        user.LastLoginTime = user.ThisLoginTime;
                        user.ThisLoginIP = IPHelper.getIPAddr();
                        user.ThisLoginTime = DateTime.Now;
                        user.LoginNumber = (user.LoginNumber ?? 0) + 1;
                        _repository.Update(user, x => x.LastLoginTime, x => x.LastLoginIP, x => x.ThisLoginTime,
                            x => x.ThisLoginIP, x => x.LoginNumber);
                    }
                }
            }
            return data;
        }
        public async Task<LoginUserDTO> BindDTO(Project_Manager_BaseInfo user)
        {
            var data=new LoginUserDTO();
               //automapper初始化一次dto
               data = Mapper.Map<Project_Manager_BaseInfo, LoginUserDTO>(user);
            data.LoginIp = IPHelper.getIPAddr();
            data.UserActionList = new List<RoleActionDTO>();
            var allRoleActions = new List<Project_SYS_RoleAction>();
            user.Roles.Where(x => !x.IsDeleted).ToList().ForEach(x =>
            { if (x.Role?.RoleActions != null) allRoleActions.AddRange(x.Role?.RoleActions); });
            if (allRoleActions.Any())
            {
                allRoleActions = allRoleActions.GroupBy(x => x.ModuleID).Select(x => new Project_SYS_RoleAction() { ID = Guid.NewGuid(), ModuleID = x.Key, Weight = x.Max(y => y.Weight) }).ToList();
            }
            //将登录者的角色存入dto
            allRoleActions.ForEach(x =>
            {
                var dto = Mapper.Map<Project_SYS_RoleAction, RoleActionDTO>(x);
                data.UserActionList.Add(dto);
            });
            var Weight = 0;
            //存入一次默认权限集方便其他地方校验时做对比验证
            data.DefActionList = new List<RoleAction_ModuleDTO>();
            var modultaction = await _moduleActionRepository.GetModultAction();
            modultaction.ForEach(
                    x =>
                    {
                        var url = x.ActionUrl.Split('/');
                        var dto = new RoleAction_ModuleDTO
                        {
                            areaName = url.Length > 1 ? url[1].ToLower() : "",
                            controllerName = url.Length > 2 ? url[2].ToLower() : "",
                            actionName = url.Length > 3 ? url[3].ToLower() : ""
                        };
                        data.DefActionList.Add(dto);
                        data.UserActionList.ForEach(y =>
                        {
                            y.ModuleDtos = y.ModuleDtos ?? new List<RoleAction_ModuleDTO>();
                            if (y.ModuleID == x.ModuleID)
                            {
                                Weight = y.Weight;
                                if ((Weight & x.Weight) == x.Weight)
                                {
                                    y.ModuleDtos.Add(new RoleAction_ModuleDTO()
                                    {
                                        ModuleID = x.ModuleID,
                                        areaName = url.Length > 1 ? url[1].ToLower() : "",
                                        controllerName = url.Length > 2 ? url[2].ToLower() : "",
                                        actionName = url.Length > 3 ? url[3].ToLower() : "",
                                        FatherModuleName = x.FatherModuleName,
                                        ModuleName = x.ModuleName,
                                        ModuleActionName = x.ActionName,
                                        ShowEnum = x.ShowEnum,
                                        ActionCls = x.ActionCls,
                                        ActionFun = x.ActionFun,
                                        OrderId = x.OrderID,
                                        ActionUrl = x.ActionUrl
                                    });
                                }
                            }
                        });
                    });
            if (data.UserActionList.Any())
            {
                //根据已有的权限做菜单绑定
                data.Menu = await _moduleDomainServices.GetLoginRoleMenu(data);
            }
            return data;
        }
        public async Task<LoginUserDTO> ChangeUserInfo(Guid ID, string nickName, string newPassword, string confirmPassword,int userChangeType, string oldpassword)
        {
            var data = new LoginUserDTO() { ID = ID, NickName = nickName, PassWord = newPassword };
            var item =await _repository.GetByKeyAsync(ID);
            if (item == null)
            {
                throw new CustomException("错误的登录账户!");
            }
            if (string.IsNullOrEmpty(nickName) && userChangeType == 0)
            {
                throw new CustomException("请输入昵称!");
            }
            if (userChangeType == 1)
            {
                if (Convert.ToBase64String(new SHA256Managed().ComputeHash(Encoding.UTF8.GetBytes(oldpassword + item.ID))) != item.PassWord)
                {
                    throw new CustomException("旧密码错误!");
                }
                if (!string.IsNullOrEmpty(newPassword) && newPassword.Length < 6 && newPassword != confirmPassword)
                {
                    throw new CustomException("请按照提示输入正确的新密码!");
                }
                if (string.IsNullOrEmpty(newPassword))
                {
                    throw new CustomException("请输入要修改的新密码!");
                }
            }
            if (userChangeType == 0)
            {
                item.NickName = nickName;
            }
            if (!string.IsNullOrEmpty(newPassword) && userChangeType == 1)
            {
                item.PassWord =
                    Convert.ToBase64String(
                        new SHA256Managed().ComputeHash(Encoding.UTF8.GetBytes(newPassword + item.ID)));
            }
            _repository.Update(item, x => x.NickName, x => x.PassWord);
            return data;
        }
        public async Task<LoginUserDTO> AddMangerBaseInfo(Project_Manager_BaseInfo model, Guid id)
        {
            var data = new LoginUserDTO();
            if (model.ID == Guid.Empty)//Add
            {
                var oldbase =await _repository.GetByConditionAsync(new DirectSpecification<Project_Manager_BaseInfo>(x => x.LoginName == model.LoginName & !x.IsDeleted));
                if (oldbase != null)
                {
                    throw new CustomException("该登录名已经存在!");
                }
                if (string.IsNullOrEmpty(model.LoginName))
                {
                    throw new CustomException("请输入登录名");
                }
                if (string.IsNullOrEmpty(model.NickName))
                {
                    throw new CustomException("请输入昵称");
                }
                if (string.IsNullOrEmpty(model.PassWord))
                {
                    throw new CustomException("请输入密码");
                }
                if (model.Roles == null)
                {
                    throw new CustomException("至少选择一个角色");
                }
                model.ID = System.Guid.NewGuid();
                model.CreateTime = DateTime.Now;
                model.PassWord =
                    Convert.ToBase64String(
                        new SHA256Managed().ComputeHash(Encoding.UTF8.GetBytes(model.PassWord + model.ID)));
                foreach (Project_Manager_Role item in model.Roles)
                {
                    item.CreateTime = DateTime.Now;
                    item.ID = Guid.NewGuid();
                    item.MemberId = model.ID;
                }
                _repository.Add(model);
            }
            else//Editor
            {
                if (string.IsNullOrEmpty(model.NickName))
                {
                    throw new CustomException("请输入昵称");
                }
                if (model.Roles == null)
                {
                    throw new CustomException("至少选择一个角色");
                }
                if (model.PassWord.Length > 0 & model.PassWord.Length < 6)
                {
                    throw new CustomException("最少输入6个字符");
                }
                var old = await _repository.GetLoginUser(new DirectSpecification<Project_Manager_BaseInfo>(x => x.ID == model.ID & !x.IsDeleted));
                old.NickName = model.NickName;
                old.PassWord = string.IsNullOrEmpty(model.PassWord) ? old.PassWord :
                        Convert.ToBase64String(
                            new SHA256Managed().ComputeHash(Encoding.UTF8.GetBytes(model.PassWord + model.ID))); ;
                if (id == model.ID & model.State == Enum_ManagerUserState.Locked)
                {
                    throw new CustomException("不能锁定当前用户状态");
                }
                old.State = model.State;
                List<Project_Manager_Role> rolelist = new List<Project_Manager_Role>();
                model.Roles.ToList().ForEach(x =>
                {
                    if (!old.Roles.Where(y=>!y.IsDeleted).Select(y => y.RoleId).Contains(x.RoleId))
                    {
                        //add
                        x.CreateTime = DateTime.Now;
                        x.ID = Guid.NewGuid();
                        x.MemberId = model.ID;
                        rolelist.Add(x);
                    }
                });
                //Editor
                var delroleid = old.Roles.Where(x => !model.Roles.Select(y => y.RoleId).Contains(x.RoleId) && !x.IsDeleted).Select(x => x.ID).ToList();
                delroleid.ForEach(x =>
                {
                    _roleRepository.LogicDelete(new DirectSpecification<Project_Manager_Role>(y=>y.ID==x));
                });
                _roleRepository.AddBatch(rolelist);
                _repository.Update(old, x => x.NickName, x => x.PassWord, x => x.State);
                data.ID = old.ID;
                data.NickName = old.NickName;
                data.PassWord = old.PassWord;
                data.State = old.State;
            }
            return data;

        }

        public async Task<IEnumerable<string>> DelManager(IEnumerable<Guid> deld, Guid uid)
        {
            if (deld.Contains(uid))
            {
                throw new CustomException("不能包含当前用户,请重新选择！");
            }
            _repository.LogicDelete(new DirectSpecification<Project_Manager_BaseInfo>(y => deld.Contains(y.ID)));
            return
                (await
                    _repository.GetManyAsync(new DirectSpecification<Project_Manager_BaseInfo>(y => deld.Contains(y.ID)))
                    ).Select(x => x.LoginName);
        }
    }
}
